package com.deceen.common.filters;

import com.deceen.common.VO.ParkingToken;
import com.deceen.common.VO.UserInfo;
import com.deceen.common.utils.HttpUtil;
import com.deceen.common.utils.JwtTokenUtil;
import com.deceen.common.utils.RedisClientUtil;
import com.deceen.demo.dao.UserMapper;
import com.deceen.demo.entity.UserEntityEo;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: zzx
 * @date: 2018/10/15 17:30
 * @description: 确保在一次请求只通过一次filter，而不需要重复执行
 */
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Resource
    private RedisClientUtil redisClientUtil;
    @Resource
    private UserMapper userMapper;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        try {

            String validateToken = HttpUtil.getAuth(request);
            if (validateToken != null) {
                String key = JwtTokenUtil.parseToken(validateToken);
//                if (key != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                if (key != null) {
                    String storeToken = redisClientUtil.getToken(key);

                    //token已过期
                    if (storeToken == null) {
                        System.out.println("认证失败1");
                        SecurityContextHolder.getContext().setAuthentication(new ParkingToken(validateToken));
                    }

                    //被其他端挤掉
                    else if (!storeToken.equals(validateToken) ) {
                        System.out.println("认证失败2");
                        SecurityContextHolder.getContext().setAuthentication(new ParkingToken(validateToken));
                    }

                    //有效
                    else {
                        //todo 刷新缓存
                        UserEntityEo user = userMapper.getUser(key);
                        if (user != null) {
                            List<SimpleGrantedAuthority> simpleGrantedAuthorities = new ArrayList<>();
                            simpleGrantedAuthorities.add(new SimpleGrantedAuthority("USER"));
                            ParkingToken authentication = new ParkingToken(new UserInfo(user.getId().toString(), user.getUsername()), simpleGrantedAuthorities);
                            System.out.println("认证成功");
                            SecurityContextHolder.getContext().setAuthentication(authentication);
                        }
                        else {
                            System.out.println("认证失败3");
                            SecurityContextHolder.getContext().setAuthentication(new ParkingToken(validateToken));
                        }
                    }
                }
            }
            filterChain.doFilter(request, response);

        } finally {

            //springboot内置的tomcat会使用线程池，请求结束后线程并没有被销毁，而是被收回到线程池，这样有可能会被一下访问者拿到其它用户的信息风险
            SecurityContextHolder.getContext().setAuthentication(null);
        }
    }
}
